package org.ssssssss.magicboot.interceptor;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.ssssssss.magicapi.core.context.RequestEntity;
import org.ssssssss.magicapi.core.interceptor.RequestInterceptor;
import org.ssssssss.magicapi.core.model.ApiInfo;
import org.ssssssss.magicapi.core.model.Options;
import org.ssssssss.magicapi.core.service.MagicAPIService;
import org.ssssssss.magicapi.core.service.MagicResourceService;
import org.ssssssss.magicapi.utils.JsonUtils;
import org.ssssssss.magicapi.utils.PathUtils;
import org.ssssssss.magicboot.model.StatusCode;
import org.ssssssss.script.MagicScriptContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Component
@Order(1)
@Slf4j
public class PermissionInterceptor implements RequestInterceptor, HandlerInterceptor {

    @Autowired
    MagicAPIService magicAPIService;

    @Autowired
    MagicResourceService magicResourceService;

    @Autowired
    private JdbcTemplate template;

    /**
     * 接口请求之前
     *
     * @param requestEntity 接口请求信息
     */
    @Override
    public Object preHandle(RequestEntity requestEntity) throws Exception {
        log.info("请求接口：{}({})", requestEntity.getApiInfo().getName(), requestEntity.getRequest().getRequestURI());
        log.info("请求头：{}", JsonUtils.toJsonStringWithoutLog(requestEntity.getHeaders()));
        log.info("请求参数：{}", JsonUtils.toJsonStringWithoutLog(requestEntity.getParameters()));
        String body = JsonUtils.toJsonStringWithoutLog(requestEntity.getRequestBody());
        log.info("请求Body：{}", body);
        return preHandle(requestEntity.getApiInfo(), requestEntity.getMagicScriptContext(), requestEntity.getRequest(), requestEntity.getResponse());
    }

    /*
     * 当返回对象时，直接将此对象返回到页面，返回null时，继续执行后续操作
     */
    @Override
    public Object preHandle(ApiInfo info, MagicScriptContext context, HttpServletRequest request, HttpServletResponse response) {
//        判断访问的接口是否需要登录
        String requireLogin = Objects.toString(info.getOptionValue(Options.REQUIRE_LOGIN), "");
        if(requireLogin.equals("false")){
            return null;
        }
        if(!StpUtil.isLogin()){
            return StatusCode.CERTIFICATE_EXPIRED.json();
        } else {
//            判断是否满足角色要求
            Map<String, Object> params = new HashMap<>();
            params.put("userId", StpUtil.getLoginId());
            List<String> roles = (List<String>) magicAPIService.execute("get", "/system/user/roles", params);
            List<String> auth_roles = new ArrayList<>();

            String auth_roles_str =  Objects.toString(info.getOptionValue(Options.ROLE), "");
            if(StringUtils.isNotBlank(auth_roles_str)){
                auth_roles.addAll(Arrays.asList(auth_roles_str.split(",")));
                roles.retainAll(auth_roles);
                if (auth_roles.size() > 0 && roles.size() == 0) {
                    return StatusCode.FORBIDDEN.json();
                }
            }
//            判断权限是否满足要求
            List<String> permissions = (List<String>) magicAPIService.execute("post", "/system/security/permissions", new HashMap<String, Object>());
            String permission = Objects.toString(info.getOptionValue(Options.PERMISSION), "");
            if (StringUtils.isNotBlank(permission) && !permissions.contains(permission)) {
                return StatusCode.FORBIDDEN.json();
            }
            ThreadContext.put("userid", (String) StpUtil.getLoginId());
        }
        return null;
    }

    @Override
    public Object postHandle(RequestEntity requestEntity, Object returnValue) throws Exception {
        if(StpUtil.isLogin()){
            try {
                HttpServletRequest request = requestEntity.getRequest();
                ApiInfo info = requestEntity.getApiInfo();
                template.update("insert into sys_oper_log(api_name, api_path, api_method, cost_time, create_by, create_date, user_agent, user_ip) values(?,?,?,?,?,?,?,?)",
//                    PathUtils.replaceSlash(groupServiceProvider.getFullName(info.getGroupId()) + "/" + info.getName()).replace("/","-"),
                        PathUtils.replaceSlash(String.format("/%s/%s", magicResourceService.getGroupName(info.getGroupId()), info.getName())),
                        request.getRequestURI(),
                        request.getMethod(),
                        System.currentTimeMillis() - requestEntity.getRequestTime(),
                        StpUtil.getLoginId(),
                        new Date(requestEntity.getRequestTime()),
                        request.getHeader("User-Agent"),
                        ServletUtil.getClientIP(request));
            } catch (Exception ignored){
                ignored.printStackTrace();
                log.error("",ignored);
            }
        }
        return null;
    }
    @Override
    public void afterCompletion(ApiInfo info, MagicScriptContext context, Object returnValue, HttpServletRequest request, HttpServletResponse response, Throwable throwable) {
        log.info("{} 执行完毕，返回结果:{}", info.getName(), JsonUtils.toJsonStringWithoutLog(returnValue));
    }

}
